﻿using RQX.Common.Core.Logger;
using System;
using System.IO.Ports;

namespace RQX.Common.Core.Hardware.Com
{
    public class MyCom
    {
        #region Init
        private readonly SerialPort _sp;
        private readonly int _baudRate;
        private readonly string _portName;
        private readonly int _dataBits;
        private readonly StopBits _stopBits;
        private readonly Parity _parity;
        private readonly bool _dtr;
        private readonly bool _rts;
        private Action<byte[]> _recv_action;

        public MyCom(MyCom source) : this(source._baudRate, source._portName, source._dataBits, source._stopBits, source._parity, source._dtr, source._rts)
        {
            _recv_action = source._recv_action;
            _sp.DataReceived += BindAction;
        }
        public MyCom(string portname) : this(9600, portname) { }
        public MyCom(int baudrate, string portname) : this(baudrate, portname, 8, StopBits.One, Parity.None) { }
        public MyCom(int baudrate, string portname, int databits, StopBits stopbits, Parity parity) : this(baudrate, portname, databits, stopbits, parity, true, true) { }
        public MyCom(int baudrate, string portname, int databits, StopBits stopbits, Parity parity, bool dtr, bool rts)
        {
            _baudRate = baudrate;
            _portName = portname;
            _dataBits = databits;
            _stopBits = stopbits;
            _parity = parity;
            _dtr = dtr;
            _rts = rts;

            _sp = new SerialPort
            {
                BaudRate = _baudRate,//波特率
                PortName = _portName,//串口号
                DataBits = _dataBits,//数据位
                StopBits = _stopBits,//停止位
                Parity = _parity,//校验位
                ReadTimeout = 3000,//设置数据读取超时为1秒
                DtrEnable = _dtr,//获取或设置一个值，该值在串行通信过程中启用数据终端就绪 (DTR) 信号。
                RtsEnable = _rts//获取或设置一个值，该值指示在串行通信中是否启用请求发送 (RTS) 信号
            };
        }
        #endregion

        #region 公共接口
        /// <summary>
        /// 绑定数据接收处理函数
        /// </summary>
        /// <param name="action"></param>
        public void BindRecvedHandler(Action<byte[]> action)
        {
            _recv_action = action;
            _sp.DataReceived += BindAction;
        }
        /// <summary>
        /// 打开串口
        /// </summary>
        public void Open()
        {
            if (!IsOpen()) _sp?.Open();
        }
        /// <summary>
        /// 关闭串口
        /// </summary>
        public void Close()
        {
            if (IsOpen())
            {
                _sp?.Close();
            }
            _sp?.Dispose();
        }
        /// <summary>
        /// 判断是否已打开
        /// </summary>
        /// <returns></returns>
        public bool IsOpen()
        {
            return _sp?.IsOpen ?? false;
        }
        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="bytes"></param>
        public void Send(byte[] bytes)
        {
            if (IsOpen())
            {
                _sp?.Write(bytes, 0, bytes.Length);
            }
            else
            {
                LogUtils.WriteDebugLog($"串口已关闭！");
            }
        }
        /// <summary>
        /// 发送
        /// </summary>
        /// <param name="text"></param>
        public void Send(string text)
        {
            if (IsOpen())
            {
                _sp?.Write(text);
            }
            else
            {
                LogUtils.WriteDebugLog($"串口已关闭！");
            }
        }
        #endregion

        #region 私有函数
        private void BindAction(object sender, SerialDataReceivedEventArgs e)
        {
            int length = _sp.BytesToRead;
            byte[] ds = new byte[length];
            _sp?.Read(ds, 0, length);
            _recv_action(ds);
        }
        #endregion
    }
}
